#include "crash_handler.h"
#include <QDebug>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QCoreApplication>

std::unique_ptr<google_breakpad::ExceptionHandler> CrashHandler::handler_;
std::string CrashHandler::userId_;
std::string CrashHandler::userName_;

bool CrashHandler::Initialize(const std::wstring& dumpPath) {
    try {
        // 确保dump目录存在
        QString dumpDir = QString::fromStdWString(dumpPath);
        QDir().mkpath(dumpDir);
        
        qDebug() << "[CRASH] Initializing crash handler, dump path:" << dumpDir;
        
        handler_ = std::make_unique<google_breakpad::ExceptionHandler>(
            dumpPath,                    // dump文件目录
            nullptr,                     // filter callback
            DumpCallback,               // minidump callback
            nullptr,                    // callback context
            google_breakpad::ExceptionHandler::HANDLER_ALL,
            MiniDumpNormal,             // dump类型
            L"",                        // pipe name (用于out-of-process)
            nullptr);                   // custom info
            
        qDebug() << "[CRASH] Crash handler initialized successfully";
        return handler_ != nullptr;
    } catch (const std::exception& e) {
        qCritical() << "[CRASH] Failed to initialize crash handler:" << e.what();
        return false;
    } catch (...) {
        qCritical() << "[CRASH] Failed to initialize crash handler: unknown exception";
        return false;
    }
}

void CrashHandler::SetUserInfo(const std::string& userId, const std::string& userName) {
    userId_ = userId;
    userName_ = userName;
    qDebug() << "[CRASH] User info set - ID:" << userId_.c_str() << "Name:" << userName_.c_str();
}

bool CrashHandler::DumpCallback(const wchar_t* dump_path,
                              const wchar_t* minidump_id,
                              void* context,
                              EXCEPTION_POINTERS* exinfo,
                              MDRawAssertionInfo* assertion,
                              bool succeeded) {
    
    QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss");
    QString dumpFile = QString::fromWCharArray(dump_path) + "/" + 
                      QString::fromWCharArray(minidump_id) + ".dmp";
    
    if (succeeded) {
        qCritical() << "[CRASH] ========== CRASH DETECTED ==========";
        qCritical() << "[CRASH] Timestamp:" << timestamp;
        qCritical() << "[CRASH] Minidump created:" << dumpFile;
        qCritical() << "[CRASH] User ID:" << userId_.c_str();
        qCritical() << "[CRASH] User Name:" << userName_.c_str();
        qCritical() << "[CRASH] Application:" << QCoreApplication::applicationName();
        qCritical() << "[CRASH] Version:" << QCoreApplication::applicationVersion();
        
        // 创建额外的崩溃信息文件
        QString infoFile = QString::fromWCharArray(dump_path) + "/" + 
                          QString::fromWCharArray(minidump_id) + "_info.txt";
        
        QFile file(infoFile);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream stream(&file);
            stream.setCodec("UTF-8");
            
            stream << "========== MMService Crash Report ==========\n";
            stream << "Timestamp: " << timestamp << "\n";
            stream << "Dump File: " << dumpFile << "\n";
            stream << "User ID: " << userId_.c_str() << "\n";
            stream << "User Name: " << userName_.c_str() << "\n";
            stream << "Application: " << QCoreApplication::applicationName() << "\n";
            stream << "Version: " << QCoreApplication::applicationVersion() << "\n";
            stream << "Process ID: " << QCoreApplication::applicationPid() << "\n";
            
            if (exinfo) {
                stream << "Exception Code: 0x" << hex << exinfo->ExceptionRecord->ExceptionCode << "\n";
                stream << "Exception Address: 0x" << hex << (uintptr_t)exinfo->ExceptionRecord->ExceptionAddress << "\n";
            }
            
            stream << "==========================================\n";
            file.close();
            
            qCritical() << "[CRASH] Additional info saved to:" << infoFile;
        }
        
        qCritical() << "[CRASH] =====================================";
        return true;
    } else {
        qCritical() << "[CRASH] Failed to create minidump at:" << QString::fromWCharArray(dump_path);
        return false;
    }
}

void CrashHandler::Cleanup() {
    if (handler_) {
        qDebug() << "[CRASH] Cleaning up crash handler";
        handler_.reset();
    }
} 